package com.example.demo.dao;

import android.util.Log;

import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;

import com.example.demo.entity.User;

import java.util.List;

import io.reactivex.rxjava3.core.Flowable;
import io.reactivex.rxjava3.core.Maybe;
import io.reactivex.rxjava3.core.Single;


/**
 * @Desc 下面用的都是rxjava的返回结果，不是写Android的，不是很懂rxjava的几个类型，
 * 有些方法用Flowable编译过不了，用Single就行了，不知道为什么
 * @Author zxp
 * @Date 2024/3/17
 */
@Dao  // 指定为Dao层
public interface UserDao {
    /*
    room+rxjava
    返回Flowable，如果select返回Flowable<User>，但是没有对应的数据，它不会emit，只有有对应的User才会emit。
                ，如果select返回Flowable<List<User>>即使没有对应的User，会emit得到一个empty的list，
                ，返回Flowable，它会一直监听数据库里数据，当数据库里的数据变化时（插入、更新（即使字段没有变化）、删除）,
                应该是这张表（其他表没试过，不知道，应该不会）的数据变动了，就会Flowable就会emit，即使select语句里查出来的跟变动的没有关系
                也就是一直订阅，不会onComplete
                如果多次执行了这个方法多次订阅，是不会重复执行的
    返回Single，没有onComplete
    返回Maybe，可以处理null，比如Maybe<User>，查询到null，那么会执行onComplete，如果不是null，会执行onSuccess(没有onNext)
     */
    /*
    room冲突策略：
    OnConflictStrategy.ABORT，默认，比如插入数据，如果冲突（如主键重复了），就会抛异常
    OnConflictStrategy.IGNORE，比如插入，如果冲突，不会抛出异常，冲突的数据不插入
    OnConflictStrategy.REPLACE，冲突替换
     */

    // --------插入--------

    /**
     * 插入1个User
     * @param user
     * @return 返回主键
     */
    @Insert
    Single<Long> insertUser(User user);

    /**
     * 插入n个User
     * @param users
     * @return 返回主键
     */
    @Insert
    Single<List<Long>> insertUsers(User...users);

    /**
     * 插入List<User>
     * @param userList
     * @return 返回主键
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    Single<List<Long>> insertUserList(List<User> userList);

    // --------删除--------

    /**
     * 删除n个User
     * @param users
     * @return 返回删除的个数
     */
    @Delete
    Single<Integer> deleteUsers(User...users);

    /**
     * 删除1个User
     * @param user
     * @return 返回删除的个数
     */
    @Delete
    Single<Integer> deleteUser(User user);

    /**
     * 根据id删除User
     * @param userId
     * @return 返回删除的个数
     */
    @Query("DELETE FROM tb_user WHERE id = :userId ")
    Single<Integer> deleteById(Long userId);

    /**
     * 根据id List删除User
     * @param ids
     * @return  返回删除的个数
     */
    @Query("DELETE FROM tb_user WHERE id IN (:ids) ")
    Single<Integer> deleteByIds(List<Long> ids);

    /**
     * 删除全部
     * @return 返回删除的个数
     */
    @Query("DELETE FROM tb_user")
    Single<Integer> deleteAll();

    // --------更新--------

    @Update
    Single<Integer> updateUsers(User...users);

    /**
     * 根据主键更新，
     * 不管字段有没有都会更新，比如age是null也会把age更新为null
     * @param user
     * @return 更新的行数
     */
    @Update
    Single<Integer> updateUser(User user);

    /**
     * 根据主键更新，
     * 但是只有字段为非null才更新
     * COALESCE是返回第一个非null，如果两个都是null则返回null
     * @param id
     * @param name
     * @param age
     * @return
     */
    @Query("UPDATE tb_user SET name = COALESCE(:name, name), age = COALESCE(:age, age) WHERE id = :id")  // 如果传进来的id为null，那么应该会把所有id为null的数据都改了
    Single<Integer> updateUserIfNotNull(Long id, String name, Integer age);

    /**
     * 根据主键更新，
     * 但是只有字段为非null才更新
     * @param user
     * @return
     */
    default Single<Integer> updateUserIfNotNull(User user) {
         return updateUserIfNotNull(user.getId(), user.getName(), user.getAge());
    }

    // --------获取--------

    /**
     * 获取全部
     * @return
     */
    @Query("SELECT * FROM tb_user")
    Single<List<User>> getAll();

    /**
     * 根据id获取，这里可能查到null，用的Maybe，如果要用Flowable或Single需要把User替换为List<User>，它们不好处理null
     * @param userId
     * @return
     */
    @Query("SELECT * FROM tb_user WHERE id == :userId")
    Maybe<User> getById(Long userId);

    /**
     * 根据id List获取
     * @param ids
     * @return
     */
    @Query("SELECT * FROM tb_user WHERE id IN (:ids)")
    Flowable<List<User>> getByIds(List<Long> ids);
}
